
#ifndef __ExampleApplication_H__
#define __ExampleApplication_H__

#include "Utilities.h"
#include "OgreConfigFile.h"
#include "ExampleFrameListener.h"

extern RaySceneQuery *raySceneQuery;

class OgreApp
{
public:
	// Constructor
	OgreApp();

	// Destructor
	~OgreApp();

	/// Start the app
	void go();

	Root *mRoot;
	Camera* mCamera;
	SceneManager* mSceneMgr;

private:

	ExampleFrameListener* mFrameListener;
	RenderWindow* mWindow;
	Ogre::String mResourcePath;

	// These internal methods package up the stages in the startup process
	/** Sets up the application - returns false if the user chooses to abandon configuration. */
	bool setup();

	/** Configures the application - returns false if the user chooses to abandon configuration. */
	bool configure();

	void chooseSceneManager();

	void createCamera();

	void createFrameListener();

	void createScene();

	void destroyScene();

	void createViewports();

	/// Method which will define the source of resources (other than current folder)
	void setupResources();

	/// Optional override method where you can create resource listeners (e.g. for loading screens)
	void createResourceListener();

	/// Optional override method where you can perform resource group loading
	/// Must at least do ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	void loadResources();
};

extern OgreApp *app;

// Event handler to add ability to alter curvature
class TerrainFrameListener : public ExampleFrameListener
{
public:
	TerrainFrameListener(RenderWindow* win, Camera* cam)
		: ExampleFrameListener(win, cam)
	{
		// Reduce move speed
		mMoveSpeed = 80;
	}

	bool frameStarted(const FrameEvent& evt)
	{
		if(ExampleFrameListener::frameStarted(evt) == false)
			return false;

		// clamp to terrain
		static Ray updateRay;
		updateRay.setOrigin(mCamera->getPosition());
		updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
		raySceneQuery->setRay(updateRay);
		RaySceneQueryResult& qryResult = raySceneQuery->execute();
		RaySceneQueryResult::iterator i = qryResult.begin();
		if(i != qryResult.end() && i->worldFragment)
		{
			mCamera->setPosition(mCamera->getPosition().x, 
				i->worldFragment->singleIntersection.y + 10, 
				mCamera->getPosition().z);
		}

		return true;
	}
};

#endif
